﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using LLoger;
using LimitatorInterfaces;

namespace AlertSystem
{
    internal static class Tester
    {
        private static DateTime _start;

        public static void Start()
        {
            _start = DateTime.Now;
        }

        public static void Stop(string msg)
        {
            MessageBox.Show(msg + ": " + (DateTime.Now - _start).Milliseconds.ToString());
        }

    }


    public sealed class AlertLoadService
    {
        private class AlertLoadServiceImplementation : ServiceBase, IDisposable
        {
            private readonly AlertsAgregator _alertAgregator = new AlertsAgregator();
            private ServiceLoader _serviceLoader;

            private readonly Dictionary<Type, KeyValuePair<ILoadProvider<object>, ILoadParser<IAlertItem>>>
                _serviceRegister =
                    new Dictionary<Type, KeyValuePair<ILoadProvider<object>, ILoadParser<IAlertItem>>>();

            public AlertsAgregator AlertsAgregator
            {
                get { return _alertAgregator; }
            }

            public AlertLoadServiceImplementation(string configPath, ILogWriter logWriter) :
                base(configPath, logWriter)
            {
                _serviceLoader = new ServiceLoader(configPath, logWriter);
            }

            public void RegisterProviders(ILoadProvider<object> loadProvider, ILoadParser<IAlertItem> loadParser)
            {
                try
                {
                    _serviceRegister.Add(loadParser.GetAlertType(),
                                         new KeyValuePair<ILoadProvider<object>, ILoadParser<IAlertItem>>(loadProvider,
                                                                                                          loadParser));
                }
                catch (Exception ex)
                {
                    var msg = "Ошибка при добавлении провайдера загрузки сообщений";
                    LogWriter.WriteLine(ex, msg);
                    throw new AddProviderException(msg, ex);
                }
            }

            public void RegisterProviders()
            {
                var ret = _serviceLoader.LoadServices();

                if (ret == null || ret.Count() == 0)
                    throw new Exception("Fuck!!!");

                foreach (var svc in ret)
                {
                    RegisterProviders(svc.Key, svc.Value);
                }
            }

            private void LoadAlerts(ILoadProvider<object> loadProvider, ILoadParser<IAlertItem> loadParser)
            {

                var loadParams = GetStartWithSettingValues(Res.LoadProviderParam);

                var data = loadProvider.LoadFrom(loadParams);
                
                _alertAgregator.Clear(loadParser.GetAlertType());
                if (data == null || !data.Any())
                    return;




                foreach (var r in data)
                {
                    _alertAgregator.Add(loadParser.ParceFrom(r));
                }


            }

            public void StartLoadAsinch(Action callback)
            {
                /*var trd = new Thread(() =>
                     {*/


                foreach (var pair in _serviceRegister)
                {
                    var svc = pair.Value;
                    LoadAlerts(svc.Key, svc.Value);
                }


                callback();
                /* });

                trd.SetApartmentState(ApartmentState.STA);
                trd.Start();*/

            }



            public void Dispose()
            {
                LogWriter.Dispose();
            }
        }


        private volatile static AlertLoadService _instance = null;
        private static object _synhObj = new object();
        private bool _configured = false;
        private AlertLoadServiceImplementation _serviceImpl;

        public static AlertLoadService Instance
        {
            get
            {
                if (_instance == null)
                    lock (_synhObj)
                        if (_instance == null)
                            _instance = new AlertLoadService();

                return _instance;
            }
        }

        public static void GonfigureService(string configPath, ILogWriter logWriter)
        {
            if (Instance._serviceImpl != null)
                throw new AlertLoadServiceException("Сервис-класс загрузки алертов ужес сконфигурирован. Повторное конфигурирование недопустимо");

            _instance._serviceImpl = new AlertLoadServiceImplementation(configPath, logWriter);
            _instance._serviceImpl.RegisterProviders();
        }

        private AlertLoadService()
        {

        }

        public void RegisterProvider(ILoadProvider<object> loadProvider, ILoadParser<IAlertItem> loadParser)
        {
            _serviceImpl.RegisterProviders(loadProvider, loadParser);
        }



        public void StartLoadAsinch(Action callback)
        {
            _serviceImpl.StartLoadAsinch(callback);
        }

        public AlertsAgregator AlertsAgregator
        {
            get { return _serviceImpl.AlertsAgregator; }
        }


    }
}
